#include "GXHT30.h"
/***************************************************************
* 函数名称: E53_IA1_IO_Init
* 说    明: E53_IA1_GPIO初始化
* 参    数: 无
* 返 回 值: 无
* 硬件配置: 
*   - GPIO0复用为I2C1_SDA（串行数据线）
*   - GPIO1复用为I2C1_SCL（串行时钟线）
*   - I2C1总线速率配置为400kHz
* 技术要点[6,7](@ref):
*   1. 采用硬件I2C控制器进行通信
*   2. 时钟频率符合SHT30最高1MHz的规格要求
*   3. 引脚复用配置需匹配硬件连接
***************************************************************/
static void E53_IA1_IO_Init(void)
{
    GpioInit();// 初始化GPIO子系统

    /* //设置GPIO_2的复用功能为普通GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);

    //设置GPIO_2为输出模式
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_OUT);

    //设置GPIO_2的复用功能为普通GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_GPIO);

    //设置GPIO_2为输出模式
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_GPIO_DIR_OUT); */

    /* I2C引脚复用配置 */
    //GPIO_0复用为I2C1_SDA
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA);

    //GPIO_1复用为I2C1_SCL
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL);

    /* I2C控制器初始化 */
    //baudrate: 400kbps
    I2cInit(WIFI_IOT_I2C_IDX_1, 400000);// 初始化I2C1控制器
    I2cSetBaudrate(WIFI_IOT_I2C_IDX_1, 400000);// 设置精确波特率
}

/***************************************************************
* 函数名称: SHT30_reset
* 说    明: SHT30复位
* 参    数: 无
* 返 回 值: 无
* 命令格式[7](@ref):
*   - 发送0x30A2软复位命令
*   时序要求：复位后需延迟至少20ms
***************************************************************/
void SHT30_reset(void)
{
    WifiIotI2cData sht30_i2c_data = {0};
    uint8_t send_data[2] = {0x30, 0xA2};// 复位命令字节

    sht30_i2c_data.sendBuf = send_data;
    sht30_i2c_data.sendLen = 2;

    I2cWrite(WIFI_IOT_I2C_IDX_1, (SHT30_Addr << 1) | 0x00, &sht30_i2c_data);
}

/***************************************************************
* 函数名称: Init_SHT30
* 说    明: 初始化SHT30，设置测量周期
* 参    数: 无
* 返 回 值: 无
模式配置[6](@ref):
*   - 发送0x2236命令启用周期测量模式（1次/秒）
*   - 中等重复性测量（相对精度：湿度±2%RH，温度±0.3℃）
* 传感器特性:
*   - 温度范围：-40℃~125℃
*   - 湿度范围：0-100%RH
***************************************************************/
void Init_SHT30(void)
{
    WifiIotI2cData sht30_i2c_data = {0};
    uint8_t send_data[2] = {0x22, 0x36};// 模式配置命令

    sht30_i2c_data.sendBuf = send_data;
    sht30_i2c_data.sendLen = 2;
    I2cWrite(WIFI_IOT_I2C_IDX_1, (SHT30_Addr << 1) | 0x00, &sht30_i2c_data);
}

/***************************************************************
* 函数名称: SHT3x_CheckCrc
* 功能描述: CRC-8校验算法实现
* 参数说明: 
*   - data[]: 待校验数据数组
*   - nbrOfBytes: 数据长度
*   - checksum: 接收到的校验码
* 返回值: 0-校验通过 1-校验失败
* 算法规范[6](@ref):
*   - 多项式：0x31（x^8 + x^5 + x^4 +1）
*   - 初始值：0xFF
*   - 输出异或：0x00
***************************************************************/
static uint8_t SHT3x_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
{

    uint8_t crc = 0xFF;
    uint8_t bit = 0;
    uint8_t byteCtr;
    const int16_t POLYNOMIAL = 0x131;// 校验多项式
    //calculates 8-Bit checksum with given polynomial
    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
        crc ^= (data[byteCtr]);
        for (bit = 8; bit > 0; --bit)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ POLYNOMIAL;
            else
                crc = (crc << 1);
        }
    }

    if (crc != checksum)
        return 1;
    else
        return 0;
}

/***************************************************************
* 函数名称: SHT3x_CalcTemperatureC
* 功能描述: 温度原始值转实际温度
* 参数说明: 
*   - u16sT: 16位原始温度值（去除低2位状态位）
* 返回值: 实际温度值（℃）
* 转换公式[7](@ref):
*   T = -45 + 175 * (raw_value / 65535)
***************************************************************/
static float SHT3x_CalcTemperatureC(uint16_t u16sT)
{

    float temperatureC = 0;

    u16sT &= ~0x0003;// 清除状态位

    temperatureC = (175 * (float)u16sT / 65535 - 45);

    return temperatureC;
}

/***************************************************************
* 函数名称: SHT3x_CalcRH
* 功能描述: 湿度原始值转实际湿度
* 参数说明: 
*   - u16sRH: 16位原始湿度值（去除低2位状态位）
* 返回值: 实际湿度值（%RH）
* 转换公式[7](@ref):
*   RH = 100 * (raw_value / 65535)
***************************************************************/
static float SHT3x_CalcRH(uint16_t u16sRH)
{

    float humidityRH = 0;

    u16sRH &= ~0x0003;// 清除状态位

    humidityRH = (100 * (float)u16sRH / 65535);

    return humidityRH;
}

/***************************************************************
* 函数名称: E53_IA1_Init
* 功能描述: 传感器整体初始化
* 参数说明: 无
* 返回值: 无
* 初始化流程[6](@ref):
*   1. GPIO和I2C接口初始化
*   2. 传感器软复位
*   3. 配置测量模式
***************************************************************/
void E53_IA1_Init(void)
{
    E53_IA1_IO_Init();// 初始化硬件接口
    Init_SHT30(); // 配置传感器工作模式
}

/***************************************************************
* 函数名称: E53_IA1_Read_Data
* 功能描述: 读取温湿度数据并解析
* 参数说明: 
*   - ReadData: 数据存储结构体指针
* 返回值: 无
* 数据采集流程[7](@ref):
*   1. 发送0xE000读取命令
*   2. 接收6字节数据（温度+CRC，湿度+CRC）
*   3. 进行CRC校验
*   4. 转换实际物理量
* 异常处理:
*   - CRC校验失败时丢弃无效数据
***************************************************************/
void E53_IA1_Read_Data(E53_IA1_Data_TypeDef *ReadData)
{
    //启动传感器采集数据

    uint8_t data[3];
    uint16_t dat, tmp;
    uint8_t SHT3X_Data_Buffer[6];// 数据缓冲区（温度3B + 湿度3B）

     /* 发送读取命令 */
    WifiIotI2cData sht30_i2c_data = {0};// 读取周期测量数据命令
    uint8_t send_data[2] = {0xE0, 0x00};
    sht30_i2c_data.sendBuf = send_data;
    sht30_i2c_data.sendLen = 2;
    sht30_i2c_data.receiveBuf = SHT3X_Data_Buffer;
    sht30_i2c_data.receiveLen = 6;
    /* 执行I2C读写操作 */
    I2cWriteread(WIFI_IOT_I2C_IDX_1, (SHT30_Addr << 1) | 0x00, &sht30_i2c_data);
    /* 温度数据解析 */
    data[0] = SHT3X_Data_Buffer[0];
    data[1] = SHT3X_Data_Buffer[1];
    data[2] = SHT3X_Data_Buffer[2];

    tmp = SHT3x_CheckCrc(data, 2, data[2]);
    if (!tmp)
    {
        dat = ((uint16_t)data[0] << 8) | data[1];
        ReadData->Temperature = SHT3x_CalcTemperatureC(dat);//温度
    }
    /* 湿度数据解析 */
    data[0] = SHT3X_Data_Buffer[3];
    data[1] = SHT3X_Data_Buffer[4];
    data[2] = SHT3X_Data_Buffer[5];

    tmp = SHT3x_CheckCrc(data, 2, data[2]);
    if (!tmp)
    {
        dat = ((uint16_t)data[0] << 8) | data[1];
        ReadData->Humidity = SHT3x_CalcRH(dat);//湿度
    }
}
